/** Copyright 2020 Zhejiang Lab and Zhejiang University. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* =============================================================
*/


import Vue from 'vue'
import Vuex from 'vuex'
import visualization from './modules/visualization'
import task from './modules/task'
import model from './modules/model'
import user from './modules/user'
import admin from './modules/admin'
import dataset from './modules/dataset'
import task_detail from './modules/task_detail'
import axios from 'axios'
import jwt_decode from 'jwt-decode'
import { ROOT_URL } from '../config'
import router from '../router'
import { setIsDialogOpen, setDialogContent } from './utils'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    auth: {
      username: localStorage.getItem('username') || '',
      is_staff: localStorage.getItem('is_staff') || false,
      token: localStorage.getItem('token') || '',
    },
    is_dialog_open: false,
    dialog_content: "",
  },
  getters: {
    auth_header: state => {
      return { 'Authorization': 'JWT ' + state.auth.token }
    },
    is_loggedin: state => {
      return state.auth.token != ''
    },
    is_staff: state => {
      return state.auth.is_staff
    }
  },
  mutations: {
    updateAuth(state, newAuth) {
      localStorage.setItem('token', newAuth.token);
      localStorage.setItem('is_staff', newAuth.is_staff);
      localStorage.setItem('username', newAuth.username);
      state.auth = newAuth;
      axios.defaults.headers.common['Authorization'] = 'JWT ' + state.auth.token;
      router.push({name: 'Welcome'})
    },
    removeAuth(state, jump=true) {
      localStorage.removeItem('token');
      localStorage.removeItem('is_staff');
      localStorage.removeItem('username');
      state.auth = { username: '', is_staff: false, token: '' };
      delete axios.defaults.headers.common["Authorization"];
      if (jump) {
        router.push({name: 'Sign In'})
      }
    },
    setIsDialogOpen, setDialogContent
  },
  actions: {
    refreshToken() {
      const payload = {
        token: this.state.token
      }
      axios.post(`${ROOT_URL}/api/user/refresh_jwt_token`, payload)
        .then((response) => {
          this.commit('updateAuth', response.data.token)
        })
        .catch((error) => {
          console.log(error)
        })
    },
    inspectToken() {
      const token = this.state.jwt;
      if (token) {
        const decoded = jwt_decode(token);
        const exp = decoded.exp
        const orig_iat = decoded.orig_iat
        if (exp - (Date.now() / 1000) < 1800 && (Date.now() / 1000) - orig_iat < 628200) {
          this.dispatch('refreshToken')
        } else if (exp - (Date.now() / 1000) < 1800) {
          // DO NOTHING, DO NOT REFRESH          
        } else {
          // PROMPT USER TO RE-LOGIN, THIS ELSE CLAUSE COVERS THE CONDITION WHERE A TOKEN IS EXPIRED AS WELL
        }
      }
    }
  },
  modules: {
    visualization,
    task,
    model,
    user,
    admin,
    dataset,
    task_detail,
  }
})

// Config axios headers and interceptors before getting into the main component.
const old_token = localStorage.getItem('token')
if (old_token != null && old_token != '') {
  axios.defaults.headers.common['Authorization'] = 'JWT ' + old_token;
}

axios.interceptors.response.use(undefined, function (error) {
  // if error response status is 401, it means the request was invalid due to expired access token
  if (error.config && error.response && error.response.status === 401) {
    console.log('interceptors.response')
    console.log(error.config)
    store.commit("removeAuth")
    store.commit("setIsDialogOpen", true)
    store.commit('setDialogContent', "登录过期，请重新登录")
  }
  return Promise.reject(error);
})

export default store